#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>

#define NUM 5  // 缓冲区大小

int queue[NUM];         // 环形缓冲区
int read_index = 0;     // 消费者读取位置
int write_index = 0;    // 生产者写入位置

sem_t empty;   // 空闲缓冲区信号量
sem_t full;    // 已填充缓冲区信号量
sem_t mutex;   // 互斥锁

// 生产者线程
void* producer(void* arg) {
    int item;
    while (1) {
        item = rand() % 1000;  // 生产数据
        
        sem_wait(&empty);      // 等待空闲缓冲区 
        sem_wait(&mutex);      // 进入临界区 
        
        // 写入缓冲区
        queue[write_index] = item;
        printf("Producer %ld: Inserted %d at %d\n", (long)arg, item, write_index);
        write_index = (write_index + 1) % NUM;  // 环形移动
        
        sem_post(&mutex);      // 离开临界区
        sem_post(&full);       // 增加已填充计数 
        
        usleep(rand() % 100000);  // 随机延迟
    }
    return NULL;
}

// 消费者线程
void* consumer(void* arg) {
    int item;
    while (1) {
        sem_wait(&full);       // 等待填充缓冲区 
        sem_wait(&mutex);      // 进入临界区
        
        // 读取缓冲区
        item = queue[read_index];
        printf("Consumer %ld: Removed %d from %d\n", (long)arg, item, read_index);
        read_index = (read_index + 1) % NUM;  // 环形移动
        
        sem_post(&mutex);      // 离开临界区
        sem_post(&empty);      // 增加空闲计数 
        
        usleep(rand() % 100000);  // 随机延迟
    }
    return NULL;
}

int main() {
    pthread_t prod[2], cons[2];
    
    // 初始化信号量
    sem_init(&empty, 0, NUM);  // 初始空闲=NUM 
    sem_init(&full, 0, 0);     // 初始已填充=0
    sem_init(&mutex, 0, 1);    // 二进制互斥锁 

    // 创建生产者/消费者线程
    for (int i = 0; i < 2; i++) {
        pthread_create(&prod[i], NULL, producer, (void*)(long)i);
        pthread_create(&cons[i], NULL, consumer, (void*)(long)i);
    }

    // 等待线程结束（实际不会结束）
    for (int i = 0; i < 2; i++) {
        pthread_join(prod[i], NULL);
        pthread_join(cons[i], NULL);
    }

    // 销毁信号量
    sem_destroy(&empty);
    sem_destroy(&full);
    sem_destroy(&mutex);
    
    return 0;
}